import fs from 'fs';
import * as blessed from 'blessed';
import { shell, sleep } from './tools';
import { program } from './blessed.d';

let menuDef = [
	{
		name: '同步服务器----',
		sub: ['设置docker仓库', '更新并重启'],
	},
	{
		name: '用户服务器----',
		sub: ['查看', '添加'],
	},
	{
		name: '客户端----',
		sub: ['设置签名', '更新基版', '打包'],
	},
	{
		name: '测试确认--',
		handler: async () => {
			let ok = await confirm('你确认吗');
			log('confirm:' + ok);
		},
	},
	{
		name: '测试输入---',
		handler: async () => {
			let v = await prompt('请输入网址', '1.com');
			log('prompt:' + v);
		},
	},
	{
		name: '测试表单---',
		handler: () => {
			testForm();
		},
	},
];

let optionCenterShrink = {
	top: 'center',
	left: 'center',
	height: 'shrink',
	width: 'shrink',
};
let testForm = () => {
	log('test form');
	let form = blessed.form({
		parent: screen,
		keys: true,
		bg: 'green',
		content: 'Submit or cancel?',
		name: 'form',
		...optionCenterShrink,
		width: 45,
		height: 18,
		border: 'line',
	});
	let set = blessed.radioset({
		parent: form,
		left: 1,
		top: 2,
		shrink: true,
		style: { bg: 'magenta' },
	});

	let radio1 = blessed.radiobutton({
		parent: set,
		mouse: true,
		keys: true,
		shrink: true,
		style: {
			bg: 'magenta',
		},
		height: 1,
		left: 0,
		top: 0,
		name: 'radio1',
		content: 'radio1',
	});

	let radio2 = blessed.radiobutton({
		parent: set,
		// mouse: true,
		keys: true,
		shrink: true,
		style: {
			bg: 'magenta',
		},
		height: 1,
		left: 15,
		top: 0,
		name: 'radio2',
		content: 'radio2',
	});

	blessed.text({
		parent: form,
		left: 2,
		top: 5,
		height: 1,
		content: 'url:',
		width: 10,
		// style: { bg: 'green' },
		bg: '#338899',
	});

	let text = blessed.textbox({
		parent: form,
		// mouse: true,
		keys: true,
		style: {
			bg: 'blue',
		},
		height: 1,
		width: 20,
		left: 10,
		top: 5,
		name: 'text',
	});

	text.on('focus', function() {
		text.readInput();
	});

	let check = blessed.checkbox({
		parent: form,
		// mouse: true,
		keys: true,
		shrink: true,
		style: {
			bg: 'magenta',
		},
		height: 1,
		left: 10,
		top: 8,
		name: 'check',
		content: 'check',
	});

	let check2 = blessed.checkbox({
		parent: form,
		mouse: true,
		keys: true,
		shrink: true,
		style: {
			bg: 'magenta',
		},
		height: 1,
		left: 20,
		top: 8,
		name: 'foooooooo2',
		content: 'foooooooo2',
	});

	screen.saveFocus();
	let submit = blessed.button({
		parent: form,
		mouse: true,
		keys: true,
		shrink: true,
		padding: {
			left: 1,
			right: 1,
		},
		left: 30,
		top: 13,
		name: 'submit',
		content: 'submit',
		style: {
			bg: 'blue',
			focus: {
				bg: 'red',
			},
		},
	});

	submit.on('press', function() {
		log('submit form');
		form.submit();
	});

	form.on('cancel', function(data) {
		log('cancel form');
	});
	form.on('submit', function(data) {
		log(JSON.stringify(data, null, 2));
		form.detach();
		// screen.focusPop();
		screen.restoreFocus();
		screen.render();
	});
	form.on('element keypress', function(el, ch, key) {
		log(`element keypress: ${el.name}, ${key.full},  gf:${screen.focused.name}`);
		if (key.full == 'escape') {
			form.detach();
		}
	});
	form.focus();
	setTimeout(function() {
		form.focusNext();
		screen.render();
	}, 100);
};

let confirm = async (title: string) => {
	let ppt = blessed.question({
		// detached: true,
		parent: screen,
		hidden: true,
		// mouse: true,
		keys: true,
		vi: true,
		...optionCenterShrink,
		border: {
			type: 'line',
		},
	});

	screen.saveFocus();
	let text = title; // + new Date().toTimeString();
	log(`ask:${text}`);
	return await new Promise(fill => {
		ppt.ask(text, (err, value) => {
			screen.restoreFocus();
			fill(value);
		});
	});
};

let prompt = async (title: string, value?: string) => {
	let ppt = blessed.prompt({
		parent: screen,
		mouse: true,
		keys: true,
		vi: true,
		...optionCenterShrink,
		border: 'line',
		bg: '#55aa55',
	});

	return await new Promise(fill => {
		ppt.readInput(title, value, (err, value) => {
			fill(value);
		});
	});
};

let screen: blessed.Widgets.Screen;
let logBox: blessed.Widgets.BoxElement;
let infoBox: blessed.Widgets.BoxElement;
let log = function(...args) {
	let box = logBox;
	// box = testBox;
	if (!box) return;
	box.pushLine(args[0]);
	box.scroll(100);
	screen.render();
};

let updateSubMenu = k => {
	if (!subMenu) return;
	log(`updateSubMenu:${k}, focused:${screen.focused.name}`);
	subMenu.clearItems();
	let { sub, handler } = menuDef[k];
	if (sub) {
		sub.forEach(v => {
			subMenu.addItem(v);
		});
	}
	if (handler) {
		// handler();
	}
};

let menu: blessed.Widgets.ListbarElement;
let createMainMenu = () => {
	let items = menuDef.map((v, k) => {
		return {
			text: v.name,
			callback: () => {
				updateSubMenu(k);
			},
		};
	});
	menu = blessed.listbar({
		left: 0,
		top: 0,
		width: '100%',
		height: 3,
		// mouse: true,
		name: 'menu',
		autoCommandKeys: true,
		items: items,
		style: {
			selected: {
				bg: 'green',
			},
			// bg: 'red',
		},
		border: {
			type: 'line',
		},
	});

	let moveTab = function(k) {
		let nk = menu.selected + k;
		if (nk < 0) nk = menu.items.length - 1;
		else if (nk >= menu.items.length) nk = 0;
		menu.selectTab(nk);
	};
	let moveSubTab = function(k) {
		let nk = subMenu.selected + k;
		if (nk < 0) nk = subMenu.items.length - 1;
		else if (nk >= subMenu.items.length) nk = 0;
		subMenu.select(nk);
	};

	menu.on('keypress', (ch, key) => {
		log(`keyprss ${ch}, ${JSON.stringify(key)} ${screen.focused.name}`);
		if (key.full == 'left') moveTab(-1);
		if (key.full == 'right') moveTab(1);
		if (key.full == 'up') moveSubTab(-1);
		if (key.full == 'down') moveSubTab(1);
		if (key.full == 'enter') {
			// menu.selectTab(menu.selected);
			let { sub, handler } = menuDef[menu.selected];
			if (handler) {
				handler();
			}
		}
		screen.render();
	});

	menu.on('select item', (el, k) => {
		log('select:' + k);
		// updateSubMenu(k);
	});

	menu.focus();
	return menu;
};

let subMenu: blessed.Widgets.ListElement;
let createSubMenu = () => {
	subMenu = blessed.list({
		top: 2,
		left: 0,
		width: 30,
		bottom: 10,
		border: 'line',
		// mouse: true,
		style: {
			selected: {
				bg: 'red',
			},
		},
		autoFocus: false,
		focusable: false,
		name: 'subMenu',
		padding: {
			left: 2,
			right: 2,
		},
	});
	return subMenu;
};

let createLogBox = () => {
	logBox = blessed.box({
		bottom: 0,
		width: '100%',
		height: 20,
		content: 'Hello {bold}world{/bold}!',
		tags: true,
		name: 'logbox',
		label: '日志',
		border: {
			type: 'line',
		},
		style: {
			fg: 'white',
			// bg: 'magenta',
		},
		focusable: false,
		input: false,
		autoFocus: false,
		mouse: true,
		scrollable: true,
		alwaysScroll: true,
		scrollbar: {
			style: {
				fg: 'white',
				bg: 'green',
			},
			track: {
				style: {
					fg: 'white',
					bg: 'yellow',
				},
			},
		},
	});

	// logBox.on('click', function(data) {
	// 	log(`click, focused:${screen.focused.name}`);
	// });

	// If box is focused, handle `enter`/`return` and give us some more content.
	// logBox.key('enter', function(ch, key) {
	// 	log('enter');
	// 	screen.render();
	// });
	return logBox;
};

let createInfoBox = () => {
	infoBox = blessed.box({
		left: 30 - 1,
		right: 0,
		top: 3 - 1,
		bottom: 20 - 1,
		border: 'line',
		name: 'testbox',
		scrollable: true,
		// mouse: true,
		autoFocus: false,
		style: {
			// bg: 'green',
		},
	});
	return infoBox;
};
async function initScreen() {
	console.log('smgr...');
	screen = blessed.screen({
		smartCSR: true,
		forceUnicode: true,
		fullUnicode: true,
		dockBorders: true,
		sendFocus: false,
		autoPadding: true,
		title: 'mb server manager',
	});

	screen.append(createMainMenu());
	screen.append(createSubMenu());
	screen.append(createLogBox());
	screen.append(createInfoBox());

	screen.key(['C-c'], function(ch, key) {
		return process.exit(0);
	});
	screen.key(['C-r'], function(ch, key) {
		reloadProgram();
	});
	screen.on('key f', (ch, key) => {
		log(`screen focused:${screen.focused.name}`);
	});
	screen.on('resize', (a, b) => {
		log(`term:${screen.width}x${screen.height}`);
		reLayout();
	});

	reLayout();
	screen.render();
}

let reLayout = () => {
	//
	let h = (screen.height as number) * 0.2;
	// logBox.height = Math.min(h, 20);
	logBox.height = 15;
	infoBox.bottom = logBox.height - 1;
	subMenu.bottom = logBox.height - 1;
};

let reloadProgram = () => {
	console.log('reload program');
	let scriptPath = '/tmp/reload-smgr.sh';
	fs.writeFileSync(scriptPath, ` sleep 0.1; node dist/smgr `);
	shell('.', `bash ${scriptPath}`);
	process.exit(0);
};

let testMain = async () => {
	while (true) {
		console.log('12345', blessed.program);
		await sleep(1000);
	}
};

let main = async () => {
	// testMain();
	initScreen();
	menu.selectTab(0);
};

main();
// testForm();

process.on('uncaughtException', err => {
	log('uncaughtException:' + err);
});

process.on('exit', () => {
	let program = screen.program;
	program.clear();
	program.showCursor();
	program.normalBuffer();
});
